Ext.namespace('Ext.ux');

/**
 * make use of Tooltip's tbar to make a button tooltip
 * guaranteed only one button tooltip is shown at any time
 * tooltip will be destroyed after desired delay
 */

Ext.ux.ButtonToolTip = {

    // last anchor for attachment
    lastAnchor : null,

    // last timer (Ext.util.DelayedTask) for detachment
    lastTimer  : null,

    /**
     * anchor - ext.Component
     */
    detachFrom : function( anchor ) {

        // cancel last timer for detachment
        if ( this.lastTimer ) {
            this.lastTimer.cancel();
            this.lastTimer = null;
        }

        // destroy tooltip
        if ( anchor.buttonTip ) {
            anchor.buttonTip.destroy();
            anchor.buttonTip = null;
        }

        // remove last anchor
        if ( anchor == this.lastAnchor ) this.lastAnchor = null;
    },

    /**
     * config - {
     *   anchor   : ext.Component for tooltip attachment
     *   xy       : Ext.ToolTip.targetXY (can obtain from Ext.EventObject),
     *   anchorEl : Ext.ToolTip.targetEl,
     *   delay    : time to be shown (in millisec)
     *   items    : Ext.ToolTip.tbar config
     * }
     */
    attachTo : function( config ) {

        if ( this.lastAnchor && this.lastAnchor.buttonTip ) {
            // guarantee only one tooltip is shown
            // detach last tooltip from last anchor
            this.detachFrom( this.lastAnchor );
        }

        // create tooltip
        config.anchor.buttonTip = new Ext.ToolTip( {
            target    : config.anchorEl,
            targetXY  : config.xy,
            autoShow  : false,
            autoHide  : false,
            autoWidth : true,
            frame     : false,
            tbar      : config.items
        } );
        config.anchor.buttonTip.show();
        this.lastAnchor = config.anchor;

        // guarantee the tooltip will not detach when mouseover
        config.anchor.buttonTip.getTopToolbar().items.each(
            function(item, idx, len) {

                if (item.type == 'button') {
                    item.addListener( 'mouseover', function() {
                        if ( Ext.ux.ButtonToolTip.lastTimer ) {
                            Ext.ux.ButtonToolTip.lastTimer.cancel();
                            Ext.ux.ButtonToolTip.lastTimer = null;
                        }
                    } );

                    item.addListener( 'mouseout', function() {
                        Ext.ux.ButtonToolTip.lastTimer = new Ext.util.DelayedTask( function() {
                            if ( config.anchor.buttonTip ) {
                                Ext.ux.ButtonToolTip.detachFrom( config.anchor );
                            }
                        } );
                        Ext.ux.ButtonToolTip.lastTimer.delay( config.delay );
                    } );
                }
            } // end foreach
        );

        // create timer for detaching the tooltip
        this.lastTimer = new Ext.util.DelayedTask( function() {
            if ( config.anchor.buttonTip ) {
                Ext.ux.ButtonToolTip.detachFrom( config.anchor );
            }
        } );
        this.lastTimer.delay( config.delay );
    }
};

// guarantee only one tooltip is shown
Ext.override( Ext.Component, {
    initComponent : function() {
        this.on( {
            'click' : function( cmp, event ) {

                if (   Ext.ux.ButtonToolTip.lastAnchor
                    && Ext.ux.ButtonToolTip.lastAnchor.buttonTip
                    && cmp != Ext.ux.ButtonToolTip.lastAnchor
                ) {
                    Ext.ux.ButtonToolTip.detachFrom(
                        Ext.ux.ButtonToolTip.lastAnchor
                    );
                }
            }
        } );
    }
} );
